﻿/*
 * *******************************************************
 *
 * 作者：HZY
 *
 * 开源地址：https://gitee.com/hzy6
 *
 * *******************************************************
 */

using System.Collections;
using Microsoft.Extensions.Caching.Memory;

namespace HZY.Framework.Core.Utils;

/// <summary>
/// 对象操作工具
/// </summary>
public static class ObjectUtil
{
    /// <summary>
    /// int
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static int ToInt32<T>(this T value)
    {
        if (value == null)
        {
            return 0;
        }

        try
        {
            if (value is string val)
            {
                if (string.IsNullOrWhiteSpace(val))
                {
                    return 0;
                }

                if (val.Count(w => w == '.') == 1)
                {
                    // 去掉小数点 之后的字符
                    val = val[..val.IndexOf('.')];
                }

                return Convert.ToInt32(val);
            }

            if (value is IConvertible convertible)
            {
                return convertible.ToInt32(null);
            }
        }
        catch (Exception)
        {
        }

        _ = int.TryParse(value.ToStr(), out int result);
        return result;
    }

    /// <summary>
    /// long
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static long ToLong<T>(this T value)
    {
        if (value == null)
        {
            return 0L;
        }

        try
        {
            if (value is string val)
            {
                if (string.IsNullOrWhiteSpace(val))
                {
                    return 0;
                }

                if (val.Count(w => w == '.') == 1)
                {
                    // 去掉小数点 之后的字符
                    val = val[..val.IndexOf('.')];
                }

                return Convert.ToInt64(val);
            }

            if (value is IConvertible convertible)
            {
                return convertible.ToInt64(null);
            }
        }
        catch (Exception)
        {
        }

        Int64.TryParse(value.ToStr(), out long result);
        return result;
    }

    /// <summary>
    /// float
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static float ToFloat<T>(this T value)
    {
        if (value == null) return 0;

        return float.TryParse(value.ToStr(), out var result) ? result : 0;
    }

    /// <summary>
    /// double
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static double ToDouble<T>(this T value)
    {
        if (value == null) return 0;

        return double.TryParse(value.ToStr(), out var result) ? result : 0;
    }

    /// <summary>
    /// decimal
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static decimal ToDecimal<T>(this T value)
    {
        if (value == null) return 0;

        return decimal.TryParse(value.ToStr(), out var result) ? result : 0;
    }

    /// <summary>
    /// Guid
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static Guid ToGuid<T>(this T value)
    {
        if (value == null) return Guid.Empty;

        return Guid.TryParse(value.ToStr(), out var result) ? result : Guid.Empty;
    }

    /// <summary>
    /// Guid?
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static Guid? ToGuidNull<T>(this T value)
    {
        if (value == null) return null;

        return Guid.TryParse(value.ToStr(), out var result) ? (Guid?)result : null;
    }

    /// <summary>
    /// GuidString
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string? ToGuidStr<T>(this T value) => value.ToGuid().ToStr();

    /// <summary>
    /// bool
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool ToBool<T>(this T value)
    {
        if (value == null) return false;

        return bool.TryParse(value.ToStr(), out var result) && result;
    }

    /// <summary>
    /// byte[]
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static byte[]? ToBytes<T>(this T value) => value == null ? null : value as byte[];

    /// <summary>
    /// 是否为空
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static bool IsNullOrEmpty(this string input)
    {
        if (input == null) return true;
        return string.IsNullOrEmpty(input);
    }

    /// <summary>
    /// 是否为空
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static bool IsNullOrWhiteSpace(this string input)
    {
        if (input == null) return true;
        return string.IsNullOrWhiteSpace(input);
    }


    /// <summary>
    /// 通过类型获取实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T CreateInstance<T>() where T : class, new()
    {
        var t = typeof(T);
        if (t.IsValueType || typeof(T) == typeof(string))
        {
            throw new HzyFrameworkCoreException("Conversion type failed!");
        }

        return (Activator.CreateInstance(t) as T) ?? throw new HzyFrameworkCoreException("Conversion failed！");
    }

    /// <summary>
    /// 将 Null 对象转换为 对象的实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <returns></returns>
    public static T NullSafe<T>(this T? model) where T : class, new()
    {
        if (model != null) return model;
        return new T(); // CreateInstance<T>();
    }

    /// <summary>
    /// 将 Null 对象转换为 对象的实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <param name="defaultInstance"></param>
    /// <returns></returns>
    public static T NullSafe<T>(this T? model, T defaultInstance) where T : class, new()
    {
        if (model != null) return model;

        return defaultInstance;
    }

    /// <summary>
    /// 获取内存缓存键
    /// </summary>
    /// <param name="memoryCache"></param>
    /// <returns></returns>
    public static IDictionary? GetMemoryCacheKeys(this IMemoryCache memoryCache)
    {
        var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
        if (memoryCache.GetType().GetField("_entries", bindingFlags)
                ?.GetValue(memoryCache) is IDictionary entries)
        {
            return entries;
        }

        var coherentState = memoryCache.GetType()
            .GetField("_coherentState", bindingFlags)?
            .GetValue(memoryCache);
        if (coherentState?.GetType()
                .GetProperty("EntriesCollection", bindingFlags)?
                .GetValue(coherentState) is IDictionary entriesCollection)
        {
            return entriesCollection;
        }

        return coherentState?.GetType()
            .GetField("_stringEntries", bindingFlags)?
            .GetValue(coherentState) as IDictionary;
    }
}